/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package rc;

import java.awt.Color;
import java.io.IOException;
import tal.drivechain.matchers.VarMatcher;
import tal.drivechain.plugin.Channel;
import tal.drivechain.variable.Variable;
import tal.remotecanvas.FrameLimiter;
import tal.remotecanvas.UIComponent;
import tal.remotecanvas.UIComponent.SHAPE;
import tal.remotecanvas.UIValueListener;
import tal.remotecanvas.rcColor;

/**
 *
 * @author Tal Eisenberg
 */
public abstract class UI extends rcModule implements UIValueListener {
    protected double fps;
    protected FrameLimiter limiter = new FrameLimiter(this);
    protected VarMatcher initTrigger;
    protected UIComponent component;

    private int maxtouches = -1;
    private String layer = null;
    private String parent = null;

    @Override
    protected void msgReceived(Variable in, long timestamp, Channel channel) {
        if (initTrigger.matches(in, channel, this)) {
            try {
                init(in);
            } catch (IOException e) {
                log("While initializing component: " + e, MSG.ERROR);
            }
        } else {
            super.msgReceived(in, timestamp, channel);
        }
    }

    @Override
    public void start() {
        limiter.setDuration(limiter.getDuration());
        super.start();
    }

    @Override
    public void stop() {
        super.stop();
        limiter.stopLimiter();
    }

    public void init(final Variable initVar) throws IOException {
        if (component==null) {
            return;
        }

        component.removeValueListener(this);
        component.addValueListener(this);

        component.initUIComponent(eventDispatcher, limiter, layer, parent);
        component.setMaxTouches(maxtouches);

        new Thread() {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();
                int round = 1;
                while(true) {
                    if (component.isInitialized()) {
                        sendToOutputs(initVar, -1);
                        return;
                    }
                    try {
                        sleep(50);
                        if (System.currentTimeMillis()-startTime>5000) {
                            log("Timeout while initializing component.", MSG.ERROR);
                            return;
                        }
                    } catch (InterruptedException ex) {}
                    round++;
                }
            }
        }.start();
    }
    public void setMaxTouches(Integer max) {
        if (max==null) return;
        this.maxtouches = max;
        if (component.isInitialized()) component.setMaxTouches(max);
    } public int getMaxTouches() {
        if (!component.isInitialized())
            return -1;
        else return component.getMaxTouches();
    }

    public void setColor(Color c) throws IOException {
        if (c==null) return;
        component.setColor(new rcColor(c));
    } public Color getColor() {
        return component.getColor().toColor();
    }

    public void setX(Integer x) {
        if (x==null) return;
        component.setLocation(x, getY());
    } public int getX() { return component.getLocation().x; }

    public void setY(Integer y) {
        if (y==null) return;
        component.setLocation(getX(), y);
    } public int getY() { return component.getLocation().y; }

    public void setRadius(Integer rad) {
        if (rad==null) return;
        component.setRadius(rad);
    } public Integer getRadius() {
        if (component.getWidth()!=component.getHeight()) return null;
        else return component.getRadius();
    }

    public void setCenterx(Integer x) {
        if (x==null) return;
        component.setCenter(x, getCentery());
    } public int getCenterx() { return component.getCenter().x; }

    public void setCentery(Integer y) {
        if (y==null) return;
        component.setCenter(getCenterx(), y);
    } public int getCentery() { return component.getCenter().y; }

    public void setArcStart(Double angle) { if (angle==null) return; component.setArcStartAngle(angle); }
    public void setArcLength(Double angle) { if (angle==null) return; component.setArcAngleLength(angle); }
    public void setRadialThickness(Double widthRadius) { if (widthRadius==null) return; component.setRadialThickness(widthRadius); }
    public double getArcStart() { return component.getArcStartAngle(); }
    public double getArcLength() { return component.getArcAngleLength(); }
    public double getRadialThickness() { return component.getRadialThickness(); }

    public void setLabel(String label) {
        if (label==null) return;
        component.setLabel(label);
    } public String getLabel() { return component.getLabel(); }

    public void setFont(Object[] font) {
        if (font==null) return;
        component.setFont((String)font[0], (Integer)font[1]);
    } public Object[] getFont() { return new Object[]{component.getFontName(), component.getFontSize()}; }

    public void setWidth(Integer width) {
        if (width==null) return;
        component.setSize(width, getHeight());
    } public int getWidth() { return component.getWidth(); }

    public void setHeight(Integer height) {
        if (height==null) return;
        component.setSize(getWidth(), height);
    } public int getHeight() { return component.getHeight(); }

    public void setShape(String shape) {
        for (SHAPE s : SHAPE.values()) {
            if (s.name().equals(shape)) {
                component.setShape(s);
                return;
            }
        }
        log("shape: Unknown shape, " + shape, MSG.ERROR);
    }
    public String getShape() {
        return component.getShape().name();
    }
    public void setEnabled(Boolean e) {
        component.setEnabled(e);
    } public boolean getEnabled() { return component.isEnabled(); }

    public void setHidden(Boolean h) {
        component.setHidden(h);
    } public boolean getHidden() { return component.isHidden(); }

    public void setLayer(String name) throws IOException {
        if (component.isInitialized()) {
            component.initUIComponent(eventDispatcher, this, layer, parent);
            this.layer = component.getLayerName();
        } else this.layer = name;
    } public String getLayer() { return component.getLayerName(); }

    public void setParent(String name) throws IOException {
        if (component.isInitialized()) {
            component.initUIComponent(eventDispatcher, this, layer, parent);
            this.parent = component.getParentName();
        } else this.parent = name;
        
    } public String getParent() { return component.getParentName(); }

    public void setFrequency(Long freq) {
        if (limiter.getDuration()!=freq) {
            limiter.setDuration(freq);
            if (!isRunning()) limiter.stopLimiter();
        }
    } public long getFrequency() { return limiter.getDuration(); }

    public void setInitTrigger(VarMatcher trigger) {
        this.initTrigger = trigger;
    } public VarMatcher getInitTrigger() { return initTrigger; }

    public void toFront() { component.toFront(); }
    public void toBack() { component.toBack(); }
}
